package com.example.demo.utils.aop;

import com.example.demo.domain.dao.ApiErrorLog;
import com.example.demo.domain.dao.ApiResultLog;
import com.example.demo.service.ApiLogService;
import com.example.demo.utils.LogUtil;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 记录接收参数，记录返回结果，去除taskId
 *
 * @author lizijian
 */
@Component
@Aspect
@Slf4j
public class LogAspect {

  private final String POINT_CUT = "execution(public * com.example.demo.controller.*.*(..)) && !execution(* com.example.demo.controller.ExceptionController.*(..))";
  @Autowired
  private ApiLogService apiLogService;


  @Pointcut(POINT_CUT)
  public void pointCut() {
  }

  @Around("pointCut()")
  public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
    ApiResultLog apiResultLog = new ApiResultLog();
    // 获取参数值
    Object[] args = joinPoint.getArgs();
    // 获取参数名
    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    String[] parameterNames = methodSignature.getParameterNames();
    StringBuilder request = new StringBuilder();
    request.append(" [");
    for (int i = 0; i < args.length; i++) {
      request.append(parameterNames[i]);
      request.append(" = ");
      request.append(args[i]);
      request.append(" , ");
    }
    request.append(" ]");
    apiResultLog.setTaskId(LogUtil.getTaskId());
    String classPath = methodSignature.getMethod().getDeclaringClass().getName();
    classPath = classPath.substring(classPath.lastIndexOf('.') + 1);
    String path=classPath + "-" + methodSignature.getMethod().getName();
    apiResultLog.setPath(path);
    apiResultLog.setRequest(request.toString());
    log.info("[{}] classInfo: {} ,args:{}", apiResultLog.getTaskId(), apiResultLog.getPath(),
        apiResultLog.getRequest());
    LogUtil.setTime();

    // 获取结果
    Object result = null;
    try {
      result = joinPoint.proceed();
      log.info(LogUtil.getMessage("result:" + result));
      apiResultLog.setResult("" + result);
      log.info(LogUtil.getMessage("time:" + LogUtil.getTime()));
      apiResultLog.setTime(LogUtil.getTime());
      LogUtil.removeTaskId();
      LogUtil.removeTime();
    } catch (Throwable throwable) {
        //异步记录至数据库
      apiLogService.insertApiError(new ApiErrorLog(LogUtil.getTaskId(),path, request.toString(),
          Arrays.toString(throwable.getStackTrace()),throwable.getMessage()),LogUtil.getTaskId());
      LogUtil.removeTaskId();
      LogUtil.removeTime();
      throw throwable;
    }
    System.out.println(apiResultLog.getTaskId());
    // 异步插入
    apiLogService.insertApiResult(apiResultLog, apiResultLog.getTaskId());
    return result;
  }

}
